package org.wii.base.web;

import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.async.TimeoutCallableProcessingInterceptor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author tanghong on 2022/12/23
 */
@Configuration
public class SpringMvcConfiguration implements WebMvcConfigurer {

    @Bean
    public CustomErrorAttributes gunsErrorAttributes() {
        return new CustomErrorAttributes();
    }

    @Bean
    public HttpMessageConverters customConverters() {
        // 创建 convert 消息转换对象
        Collection<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        // 创建与配置 Fastjson 对象
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        fastJsonConfig.setCharset(Charset.forName("UTF-8"));
        fastConverter.setFastJsonConfig(fastJsonConfig);
        // 将convert 添加到 converters
        messageConverters.add(fastConverter);
        List<SerializerFeature> featureList = new ArrayList<>(10);
        featureList.add(SerializerFeature.DisableCircularReferenceDetect);
        //featureList.add(SerializerFeature.WriteMapNullValue);
        fastJsonConfig.setSerializerFeatures(ArrayUtil.toArray(featureList, SerializerFeature.class));
        //处理中文乱码问题
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON);
        fastMediaTypes.add(MediaType.TEXT_PLAIN);
        fastConverter.setSupportedMediaTypes(fastMediaTypes);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        messageConverters.add(fastConverter);
        return new HttpMessageConverters(true, messageConverters);
    }

    @Override
    public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {
        configurer.setDefaultTimeout(30 * 1000L);
        configurer.registerCallableInterceptors(timeoutInterceptor());
        configurer.setTaskExecutor(iWiiAsyncExecutor());
    }

    @Bean
    public TimeoutCallableProcessingInterceptor timeoutInterceptor() {
        return new TimeoutCallableProcessingInterceptor();
    }

    @Bean("iWiiMvcAsyncExecutor")
    public ThreadPoolTaskExecutor iWiiAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setThreadNamePrefix("iWiiMvcAsync");
        //设置线程池中线程的个数
        executor.setCorePoolSize(300);
        //设置线程池中可容纳线程的最大个数
        executor.setMaxPoolSize(1000);
        //设置线程存活时间
        executor.setKeepAliveSeconds(360);
        //设置等待处理的任务队列
        executor.setQueueCapacity(1000);
        //设置超过最大线程数时需要执行的策略（等待策略）
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        return executor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new InitParameterHandler()).addPathPatterns("/**");
    }
}
